using System;
using System.Collections.Generic;
using UnityEngine;

public class AIController : MonoBehaviour
{
	[SerializeField]
	private CharacterInformation info;

	[SerializeField]
	private AimHelper aimHelper;

	[SerializeField]
	private CharacterFighting fighting;

	[SerializeField]
	private CharacterHealth health;

	[SerializeField]
	private CharacterRotation rotation;

	[SerializeField]
	private CharacterMovement movement;

	[SerializeField]
	private CharacterStep step;

	[Header("AI Proccessing")]
	private CharacterInformation[] listEnemy;

	private AIController[] otherAIs;

	[SerializeField]
	private float punchRange;

	[SerializeField]
	private float gunRange;

	[SerializeField]
	private float sinceCheckDamage;

	private float rangeDelta;

	private float startDelay = 2f;

	private float delayCheck = 3f;

	private bool canAttack;

	[SerializeField]
	private DamageInfomation[] damageInfos;

	private CharacterInformation targetEnemy;

	private Weapon targetWeapon;

	private Transform specialTarget;

	private float playingRange => (!fighting.hasWeapon) ? punchRange : gunRange;

	private void Awake()
	{
		CharacterHealth characterHealth = health;
		characterHealth.OnStickmanTakeDamage = (Action<CharacterInformation, float>)Delegate.Combine(characterHealth.OnStickmanTakeDamage, new Action<CharacterInformation, float>(OnStickmanTakeDamage));
	}

	private void Update()
	{
		if (info.freeze)
		{
			return;
		}
		if (startDelay > 0f)
		{
			startDelay -= Time.deltaTime;
		}
		else
		{
			if (!info.isAlive)
			{
				return;
			}
			if (!fighting.hasWeapon)
			{
				targetWeapon = GetTargetWeapon();
			}
			if (targetEnemy == null || !targetEnemy.isAlive)
			{
				targetEnemy = GetNearestTargetEnemy();
			}
			delayCheck -= Time.deltaTime;
			if (delayCheck <= 0f)
			{
				delayCheck = 2f;
				if (!info.isDemo)
				{
					GetMostDamageEnemy();
				}
			}
			if (targetEnemy == null || !targetEnemy.isAlive)
			{
				step.StopRunAnimation();
				return;
			}
			if (UnityEngine.Random.Range(0, 1000) < 3 || info.wallNormal != Vector3.zero)
			{
				AIJump();
			}
			if (info.isDemo && UnityEngine.Random.Range(0, 1000) < 6)
			{
				AIJump();
			}
			if (!(specialTarget != null))
			{
				if (!fighting.hasWeapon && targetWeapon != null)
				{
					ToTargetWeapon();
					Vector3 position = targetWeapon.transform.position;
					float y = position.y;
					Vector3 position2 = info.mainRig.position;
					if (y > position2.y)
					{
						Vector3 position3 = targetWeapon.transform.position;
						float x = position3.x;
						Vector3 position4 = info.mainRig.position;
						if (Mathf.Abs(x - position4.x) < punchRange)
						{
							AIJump();
						}
					}
				}
				else if (targetEnemy != null)
				{
					KeepRangeWithStickman();
				}
			}
			if (targetEnemy != null)
			{
				AimTargetStickman(targetEnemy.mainRig.position);
				if (fighting.hasWeapon && canAttack)
				{
					AttackTargetStickman();
				}
				else if (Vector3.Distance(info.mainRig.position, targetEnemy.mainRig.position) < punchRange)
				{
					AttackTargetStickman();
				}
			}
		}
	}

	private void OnDestroy()
	{
		if (health != null)
		{
			CharacterHealth characterHealth = health;
			characterHealth.OnStickmanTakeDamage = (Action<CharacterInformation, float>)Delegate.Remove(characterHealth.OnStickmanTakeDamage, new Action<CharacterInformation, float>(OnStickmanTakeDamage));
		}
	}

	private void OnStickmanTakeDamage(CharacterInformation attacker, float damage)
	{
		if (attacker == null)
		{
			return;
		}
		DamageInfomation[] array = damageInfos;
		int num = 0;
		DamageInfomation damageInfomation;
		while (true)
		{
			if (num < array.Length)
			{
				damageInfomation = array[num];
				if (damageInfomation.attacker == attacker)
				{
					break;
				}
				num++;
				continue;
			}
			return;
		}
		damageInfomation.totalDamage += damage;
	}

	public void ResetDelay()
	{
		startDelay = 2f;
	}

	public void RegisterEnemies(CharacterInformation[] inputList)
	{
		listEnemy = inputList;
		damageInfos = new DamageInfomation[listEnemy.Length];
		for (int i = 0; i < listEnemy.Length; i++)
		{
			damageInfos[i] = new DamageInfomation(listEnemy[i]);
		}
		rangeDelta = UnityEngine.Random.Range(0.2f, 0.5f);
	}

	private CharacterInformation GetMostDamageEnemy()
	{
		float num = 0f;
		CharacterInformation result = null;
		DamageInfomation[] array = damageInfos;
		foreach (DamageInfomation damageInfomation in array)
		{
			if (!(damageInfomation.attacker == info))
			{
				if (damageInfomation.totalDamage > num)
				{
					num = damageInfomation.totalDamage;
					result = damageInfomation.attacker;
				}
				damageInfomation.Reset();
			}
		}
		sinceCheckDamage = 0f;
		return result;
	}

	private CharacterInformation GetNearestTargetEnemy()
	{
		List<CharacterInformation> list = new List<CharacterInformation>();
		CharacterInformation[] array = listEnemy;
		foreach (CharacterInformation characterInformation in array)
		{
			if (characterInformation != info && characterInformation.isAlive)
			{
				list.Add(characterInformation);
			}
		}
		if (list.Count == 0)
		{
			return null;
		}
		return list[UnityEngine.Random.Range(0, list.Count)];
	}

	private Weapon GetTargetWeapon()
	{
		float num = 1000f;
		Weapon result = null;
		Weapon[] array = UnityEngine.Object.FindObjectsOfType<Weapon>();
		Weapon[] array2 = array;
		foreach (Weapon weapon in array2)
		{
			if (weapon.owner != null)
			{
				continue;
			}
			Vector3 position = weapon.transform.position;
			if (!(position.y <= -6.5f))
			{
				float num2 = Vector3.Distance(info.mainRig.position, weapon.transform.position);
				if (num2 < num)
				{
					result = weapon;
					num = num2;
				}
			}
		}
		return result;
	}

	private void KeepRangeWithStickman()
	{
		if (targetEnemy != null)
		{
			Vector3 position = targetEnemy.mainRig.position;
			float z = position.z;
			Vector3 position2 = info.mainRig.position;
			float num = Mathf.Abs(z - position2.z);
			float num2 = 0f;
			float num3 = 1f;
			if (!fighting.hasWeapon)
			{
				num3 = ((!((double)fighting.sincePunch < 0.5)) ? 1f : 2f);
			}
			if (num < playingRange * (1f - rangeDelta) * num3)
			{
				num2 = -1f;
			}
			else if (num > playingRange * (1f + rangeDelta) * num3)
			{
				num2 = 1f;
			}
			Vector3 position3 = targetEnemy.mainRig.position;
			float z2 = position3.z;
			Vector3 position4 = info.mainRig.position;
			float num4 = Mathf.Sign(z2 - position4.z);
			num4 *= num2;
			if (num4 != 0f)
			{
				step.PlayRunAnimation();
				movement.Move(num4);
				CheckWallToJump(num4);
				canAttack = false;
			}
			else
			{
				step.StopRunAnimation();
				Vector3 position5 = targetEnemy.mainRig.position;
				float z3 = position5.z;
				Vector3 position6 = info.mainRig.position;
				float num5 = Mathf.Sign(z3 - position6.z);
				canAttack = true;
			}
		}
	}

	private void ToTargetWeapon()
	{
		Vector3 position = targetWeapon.transform.position;
		float z = position.z;
		Vector3 position2 = info.mainRig.transform.position;
		float num = Mathf.Sign(z - position2.z);
		step.PlayRunAnimation();
		movement.Move(num);
		CheckWallToJump(num);
	}

	private void AimTargetStickman(Vector3 target)
	{
		aimHelper.TargetAim(targetEnemy.mainRig.transform.position);
	}

	private void AttackTargetStickman()
	{
		if (UnityEngine.Random.Range(0, 1000) < 3)
		{
			AIJump();
		}
		fighting.Attack();
	}

	private void CheckWallToJump(float side)
	{
		if (info.sinceWall < 0.4f)
		{
			AIJump();
		}
	}

	private void AIJump()
	{
		if (info.sinceJumped < 0.2f)
		{
			return;
		}
		if (info.sinceWall > info.sinceGrounded)
		{
			info.wallNormal = Vector3.zero;
		}
		if (info.isGrounded || info.sinceGrounded < 0.2f || info.wallNormal != Vector3.zero)
		{
			info.sinceGrounded = 1f;
			info.sinceWall = 1f;
			info.sinceJumped = 0f;
			if (info.wallNormal != Vector3.zero)
			{
				info.wallNormal = Vector3.zero;
			}
			info.jumpTick = 1;
			movement.Jump();
		}
		else if (info.jumpTick > 0)
		{
			info.sinceGrounded = 1f;
			info.sinceWall = 1f;
			info.sinceJumped = 0f;
			info.jumpTick--;
			movement.Jump();
		}
	}
}
